from typing import Optional, List
from sqlalchemy.orm import Session
from sqlalchemy import or_, func
from fastapi import HTTPException, status

from app.models.user import User
from app.models.schemas import UserCreate, UserUpdate
from app.services.base import BaseService
from app.utils.auth import get_password_hash, verify_password


class UserService(BaseService[User, UserCreate, UserUpdate]):
    def get_multi(
        self,
        db: Session,
        *,
        skip: int = 0,
        limit: int = 100,
        filters: Optional[dict] = None,
    ) -> List[User]:
        """获取多个记录，排除超级管理员"""
        query = db.query(User).filter(User.is_superuser != 1)
        if filters:
            for field, value in filters.items():
                if hasattr(User, field):
                    query = query.filter(getattr(User, field) == value)
        return query.offset(skip).limit(limit).all()

    def count(self, db: Session, filters: Optional[dict] = None) -> int:
        """获取记录总数，排除超级管理员"""
        query = db.query(func.count(User.id)).filter(User.is_superuser != 1)
        if filters:
            for field, value in filters.items():
                if hasattr(User, field):
                    query = query.filter(getattr(User, field) == value)
        return query.scalar()

    """用户服务类"""

    def __init__(self):
        super().__init__(User)

    def get_by_username(self, db: Session, username: str) -> Optional[User]:
        """根据用户名获取用户"""
        return db.query(User).filter(User.username == username).first()

    def get_by_email(self, db: Session, email: str) -> Optional[User]:
        """根据邮箱获取用户"""
        return db.query(User).filter(User.email == email).first()

    def create_user(self, db: Session, *, user_in: UserCreate) -> User:
        """创建用户"""
        hashed_password = get_password_hash(user_in.password)
        user_data = user_in.dict(exclude={"password"})
        user_data["hashed_password"] = hashed_password

        db_user = User(**user_data)
        db.add(db_user)
        db.commit()
        db.refresh(db_user)
        return db_user

    def authenticate(
        self, db: Session, *, username: str, password: str
    ) -> Optional[User]:
        """验证用户"""
        user = self.get_by_username(db, username)
        if not user:
            return None
        if not verify_password(password, user.hashed_password):
            return None
        return user

    def search_users(
        self, db: Session, *, search: str, skip: int = 0, limit: int = 100
    ) -> List[User]:
        """搜索用户，排除超级管理员"""
        search_pattern = f"%{search}%"
        query = (
            db.query(User)
            .filter(
                or_(
                    User.username.ilike(search_pattern),
                    User.email.ilike(search_pattern),
                    User.full_name.ilike(search_pattern),
                ),
                User.is_superuser != 1,
            )
            .offset(skip)
            .limit(limit)
        )
        return query.all()

    def count_search_users(self, db: Session, *, search: str) -> int:
        """搜索用户总数，排除超级管理员"""
        search_pattern = f"%{search}%"
        query = db.query(func.count(User.id)).filter(
            or_(
                User.username.ilike(search_pattern),
                User.email.ilike(search_pattern),
                User.full_name.ilike(search_pattern),
            ),
            User.is_superuser != 1,
        )
        return query.scalar()

    def toggle_active(self, db: Session, *, user_id: int) -> Optional[User]:
        """切换用户激活状态"""
        user = self.get(db, user_id)
        if user:
            user.is_active = not user.is_active
            db.commit()
            db.refresh(user)
        return user

    def is_username_taken(self, db: Session, username: str) -> bool:
        """检查用户名是否已被使用"""
        user = self.get_by_username(db, username)
        return user is not None

    def is_email_taken(self, db: Session, email: str) -> bool:
        """检查邮箱是否已被使用"""
        user = self.get_by_email(db, email)
        return user is not None

    def update_password(self, db: Session, *, user: User, new_password: str) -> User:
        """更新用户密码"""
        hashed_password = get_password_hash(new_password)
        user.hashed_password = hashed_password
        db.commit()
        db.refresh(user)
        return user

    def get_active_users(
        self, db: Session, *, skip: int = 0, limit: int = 100
    ) -> List[User]:
        """获取活跃用户列表"""
        return (
            db.query(User)
            .filter(User.is_active == True)
            .offset(skip)
            .limit(limit)
            .all()
        )

    def count_active_users(self, db: Session) -> int:
        """获取活跃用户总数"""
        return db.query(func.count(User.id)).filter(User.is_active == True).scalar()

    def update(self, db: Session, *, db_obj: User, obj_in: UserUpdate) -> User:
        """更新用户信息（重写基类方法以添加唯一性验证）"""
        # 获取更新数据
        try:
            update_data = obj_in.dict(exclude_unset=True)
        except AttributeError:
            # 如果dict方法不存在，使用备用方法
            update_data = {k: v for k, v in obj_in.__dict__.items() if v is not None}

        # 移除None值和空字符串
        update_data = {
            k: v for k, v in update_data.items() if v is not None and v != ""
        }

        # 检查用户名唯一性
        if "username" in update_data and update_data["username"]:
            existing_user = self.get_by_username(db, update_data["username"])
            if existing_user and existing_user.id != db_obj.id:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST, detail="用户名已存在"
                )

        # 检查邮箱唯一性
        if "email" in update_data and update_data["email"]:
            existing_user = self.get_by_email(db, update_data["email"])
            if existing_user and existing_user.id != db_obj.id:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST, detail="邮箱已存在"
                )

        # 更新字段
        for field, value in update_data.items():
            if hasattr(db_obj, field):
                setattr(db_obj, field, value)

        db.commit()
        db.refresh(db_obj)
        return db_obj


# 创建全局实例
user_service = UserService()
